/*  
 * Copyright 2007 MBARI 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */
package org.mbari.timeline.model;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicBoolean;

import org.mbari.timeline.DateUtil;
import org.mbari.timeline.model.Event;

import com.domainlanguage.time.Duration;
import com.domainlanguage.time.TimePoint;

import junit.framework.TestCase;

/**
 * Test that an event has the following properties:
 * know the time it is currently scheduled to occur at, observable property.
 * the amount of time the event will last, observable
 * @author Andrew Chase
 *
 */
public class TestEvent extends TestCase {

	private Event eventModel;

	protected void setUp() throws Exception {
		super.setUp();
		eventModel = new Event();
	}
	
	public void testDurationChange() throws Exception{
		testObservableProperty(Duration.class, "duration", Duration.milliseconds(100), Duration.days(3));
	}

	public void testTimeChange() throws Exception{
		final TimePoint timePoint = DateUtil.BEGIN_2007;
		final TimePoint nextTimePoint = timePoint.plus(Duration.days(5));
		testObservableProperty(TimePoint.class, "time", timePoint, nextTimePoint);
	}
	
	private void testObservableProperty(Class type, String propertyname, final Object firstValue, final Object secondValue) throws Exception{
		String upperCased = propertyname.substring(0,1).toUpperCase() + propertyname.substring(1);
		Class[] params = {type};
		Method setterMethod = Event.class.getMethod("set" + upperCased, params);
		Method getterMethod = Event.class.getMethod("get" + upperCased, new Class[0]);
		final AtomicBoolean propertyChanged = new AtomicBoolean();
		propertyChanged.set(false);
		Object[] setterArgs = {firstValue}; 
		setterMethod.invoke(eventModel, setterArgs);
		eventModel.addPropertyChangeListener(new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				assertEquals(evt.getNewValue(), secondValue);
				assertEquals(evt.getOldValue(), firstValue);
				propertyChanged.set(true);
			}
		});
		Object[] setterArgs2 = {secondValue};
		setterMethod.invoke(eventModel, setterArgs2);
		Object[] noArgs = {};
		assertEquals(getterMethod.invoke(eventModel, noArgs), secondValue);
		assertTrue(propertyChanged.get());
	}
}
